package extend_widget

import (
	"clientDemo/ui/fyne_ui/common"
	"clientDemo/ui/fyne_ui/widget"
	"clientDemo/ui/fyne_ui/widget/interface"
	"clientDemo/utils"
	"fmt"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"image"
	"image/color"
	"image/draw"
	"sort"
)

var _ widgetcommon.IWidgetItem = (*Image9Sprite)(nil)

func init() {
	widget.RegWidget("Widget9Sprite", "9宫格", NewImage9Sprite)
}

type Image9Sprite struct {
	*WidgetContainer
	Image *canvas.Image
	*Action
	rootNode widgetcommon.IWidgetItem //父节点
	File     string
	name     string
	scale    float32
	imgSize  fyne.Size
}

func NewImage9Sprite(name string, skinInfo widgetcommon.IWidgetSkin, rootNode widgetcommon.IWidgetItem) widgetcommon.IWidgetItem {
	if skinInfo == nil {
		return nil
	}
	o := &canvas.Image{}
	o.FillMode = canvas.ImageFillOriginal
	_image := &Image9Sprite{
		Image:  o,
		Action: &Action{},
		WidgetContainer: &WidgetContainer{
			Container: &Container{
				name: name,
			},
			Border: &canvas.Rectangle{
				FillColor:   color.Transparent,
				StrokeColor: color.RGBA{255, 0, 0, 255}, //黄色
				StrokeWidth: 2,
			},
		},
		rootNode: rootNode,
	}
	_image.WidgetContainer.ac = _image.Action
	_image.IUserInfo = common.NewWidgetUserInfo(name, skinInfo.GetSkinName(), _image)
	_image.WidgetContainer.SetObjects([]fyne.CanvasObject{_image.Image})
	_image.SetBase(_image, rootNode)
	_image.ExtendBaseWidget(_image)
	_image.name = name
	return _image
}
func (i *Image9Sprite) SetProperty(key, value string, isProperty bool) {
	i.WidgetContainer.SetProperty(key, value, isProperty)
	if key == "BackTexture" {
		i.SetImagePath(value)
	}
	if key == "Scale" {
		i.scale = utils.ParseFloat32(value)
		newSize := fyne.NewSize(i.imgSize.Width*i.scale, i.imgSize.Height*i.scale)
		i.Image.SetMinSize(newSize)
	}
	if key == "InsetsRect" {
		arr := utils.SplitInt(value, " ")
		if len(arr) < 4 {
			return
		}
		pointList := []*image.Point{}
		for i := 0; i < len(arr)-3; i += 4 {
			pointList = append(pointList, &image.Point{int(arr[i]), int(arr[i+1])})
			pointList = append(pointList, &image.Point{int(arr[i+2]), int(arr[i+3])})
		}
		err, imgMap := splitImage(i.Image.Image, pointList...,
		//&image.Point{17, 32},
		//&image.Point{18, 33},
		//&image.Point{49, 33},
		//&image.Point{50, 33},
		)
		if err != nil {
			return
		}
		bagImg := mergeImages9sprite(imgMap,
			fyne.NewSize(float32(2*i.Image.Image.Bounds().Dx()+1), float32(50)),
			fyne.NewSize(float32(i.Image.Image.Bounds().Dx()+1), float32(1)),
		)
		bImage := canvas.NewImageFromImage(bagImg)
		i.scale = 1
		i.imgSize = fyne.NewSize(float32(bagImg.Bounds().Dx())*i.scale, float32(bagImg.Bounds().Dy())*i.scale)
		bImage.SetMinSize(i.imgSize)

		i.Image = bImage
		//i.Image.FillMode = canvas.ImageFillOriginal
		i.WidgetContainer.SetObjects([]fyne.CanvasObject{i.Image})
		i.Image.Refresh()
	}
}
func (i *Image9Sprite) SetImagePath(path string) {
	if i.File == path {
		return
	}
	i.File = path
	i.Image.File = path // 设置图片路径
	i.Image.Refresh()   // 刷新控件以显示新图片
}

func (i *Image9Sprite) MinSize() fyne.Size {
	return i.Image.MinSize()
	//i.ExtendBaseWidget(i)
	//return i.BaseWidget.MinSize()
}

// ┌───────┬─────────────────┬───────┐
// │   1   │        4        │   7   │
// ├───────┼─────────────────┼───────┤
// │       │                 │       │
// │   2   │        5        │   8   │
// │       │                 │       │
// ├───────┼─────────────────┼───────┤
// │   3   │        6        │   9   │
// └───────┴─────────────────┴───────┘
// ┌───────┬─────────────────┬──────┬─────────────────────────┬──────┐
// │   1   │        4        │   7  │           10            │   13 │
// ├───────┼─────────────────┼──────┼─────────────────────────┼──────┤
// │       │                 │      │                         │      │
// │   2   │        5        │   8  │           11            │   14 │
// │       │                 │      │                         │      │
// ├───────┼─────────────────┼──────┼─────────────────────────┼──────┤
// │   3   │        6        │   9  │           12            │   15 │
// └───────┴─────────────────┴──────┴─────────────────────────┴──────┘
func splitImage(img image.Image, point ...*image.Point) (error, map[int]image.Image) {
	if len(point) < 2 || len(point)%2 != 0 {
		return fmt.Errorf("图片生成失败, 输入点非法"), nil
	}
	var mapWidthStep = map[int]int{}
	var mapHeightStep = map[int]int{}
	var prev *image.Point
	for i := 0; i < len(point); i++ {
		p := point[i]
		if i < 2 {
			if prev != nil {
				if prev.X > p.X || prev.Y > p.Y {
					return fmt.Errorf("图片生成失败, 输入点非法"), nil
				}
			}
			mapWidthStep[i] = p.X
			mapHeightStep[i] = p.Y
			prev = p
			continue
		} else {
			if prev.Y > p.Y {
				return fmt.Errorf("图片生成失败, 输入点非法"), nil
			}
		}
		mapWidthStep[i] = p.X
		prev = p
	}
	if len(mapWidthStep) == 0 || len(mapHeightStep) == 0 {
		return fmt.Errorf("图片生成失败, 输入点非法"), nil
	}
	// 获取图片的尺寸
	width := img.Bounds().Dx()
	height := img.Bounds().Dy()
	if mapWidthStep[len(mapWidthStep)-1] >= width || mapWidthStep[len(mapWidthStep)-1] >= width {
		return fmt.Errorf("图片生成失败, 输入点非法"), nil
	}
	mapWidthStep[len(mapWidthStep)] = int(width)
	mapHeightStep[len(mapHeightStep)] = int(height)

	calcRectMap := map[int]*image.Rectangle{}
	for i := 0; i < len(mapWidthStep); i++ {
		for j := 0; j < len(mapHeightStep); j++ {
			index := i*3 + j + 1
			var startPointY int
			if j == 0 {
				startPointY = 0
			} else {
				startPointY = mapHeightStep[j-1]
			}
			var startPointX int
			if i == 0 {
				startPointX = 0
			} else {
				startPointX = mapWidthStep[i-1]
			}
			o := &image.Rectangle{
				Min: image.Point{startPointX, startPointY},
				Max: image.Point{mapWidthStep[i], mapHeightStep[j]},
			}
			calcRectMap[index] = o
		}
	}

	pointList := []*image.Point{}

	pointList = append(pointList, point...)
	pointList = append(pointList, &image.Point{width, height})
	//排序pointList
	sort.Slice(pointList, func(i, j int) bool {
		return pointList[i].X < pointList[j].X
	})

	genCount := (len(point) + 1) * 3
	_ = genCount
	// 生成切分格子
	imgMap := map[int]image.Image{}
	for i := 1; i <= len(calcRectMap); i++ {
		imgMap[i] = segmentPic(&img, calcRectMap[i])
	}
	return nil, imgMap
}
func segmentPic(img *image.Image, rc *image.Rectangle) *image.RGBA {
	newImg := image.NewRGBA(image.Rect(0, 0, rc.Dx(), rc.Dy()))
	draw.Draw(newImg, newImg.Bounds(), *img, image.Point{rc.Min.X, rc.Min.Y}, draw.Src)
	return newImg
}
func mergeImages9sprite(imgMap map[int]image.Image, addSize ...fyne.Size) image.Image {
	if len(imgMap) == 0 || addSize == nil {
		return nil
	}
	// 计算合并后图像的宽度和高度
	var mapWidthStep = map[int]int{}
	var mapHeightStep = map[int]int{}
	for i := 1; i <= len(imgMap); i++ {
		img, ok := imgMap[i]
		if !ok {
			continue
		}
		indexX := (i - 1) / 3
		tWidth := img.Bounds().Dx()
		lastWidth := mapWidthStep[indexX]
		if lastWidth < tWidth {
			mapWidthStep[indexX] = tWidth
		}

		indexY := (i - 1) % 3
		tHeight := img.Bounds().Dy()
		lastHeight := mapHeightStep[indexY]
		if lastHeight < tHeight {
			mapHeightStep[indexY] = tHeight
		}
	}

	var mapWidthIndex = map[int]int{}
	var mapHeightIndex = map[int]int{}
	totalWidth := 0
	totalHeight := 0
	for i := 0; i < len(mapWidthStep); i++ {
		mapWidthIndex[i] = totalWidth
		totalWidth += mapWidthStep[i]
		if i%2 == 1 {
			order := (i - 1) / 2
			// 纵向拉伸
			totalWidth += int(addSize[order].Width)
		}
		mapWidthIndex[i+1] = totalWidth
	}
	for i := 0; i < len(mapHeightStep); i++ {
		mapHeightIndex[i] = totalHeight
		totalHeight += mapHeightStep[i]
		if i%2 == 1 {
			totalHeight += int(addSize[0].Height)
		}
		mapHeightIndex[i+1] = totalHeight
	}
	// 创建一个新的图像
	mergedImage := image.NewRGBA(image.Rect(0, 0, totalWidth, totalHeight))

	// 将每个图像绘制到新图像上
	xOffset := 0
	yOffset := 0

	//  ┌───0───┬────────1────────┬───2──┬──────────3──────────────┬───4──┐
	//0 │   1   │        4        │   7  │           10            │   13 │
	//  ├───────┼─────────────────┼──────┼─────────────────────────┼──────┤
	//  │       │                 │      │                         │      │
	//1 │   2   │        5        │   8  │           11            │   14 │
	//  │       │                 │      │                         │      │
	//  ├───────┼─────────────────┼──────┼─────────────────────────┼──────┤
	//2 │   3   │        6        │   9  │           12            │   15 │
	//  └───────┴─────────────────┴──────┴─────────────────────────┴──────┘
	for i := 1; i <= len(imgMap); i++ {
		img := imgMap[i]
		if img == nil {
			continue
		}
		indexX := (i - 1) / 3
		indexY := (i - 1) % 3
		xOffset = mapWidthIndex[indexX]
		yOffset = mapHeightIndex[indexY]
		xOffsetNext := mapWidthIndex[indexX+1]
		yOffsetNext := mapHeightIndex[indexY+1]
		stretchDraw(mergedImage,
			image.Rect(
				xOffset,
				yOffset,
				xOffsetNext, //+newWidth,
				yOffsetNext, //+newHeight
			),
			img)
	}
	return mergedImage
}

// stretchDraw 绘制时拉伸源图像到目标区域
func stretchDraw(dst *image.RGBA, dstRect image.Rectangle, src image.Image) {
	// 创建一个新的图像用于拉伸
	stretched := image.NewRGBA(image.Rectangle{
		Min: image.Point{0, 0},
		Max: image.Point{dstRect.Dx(), dstRect.Dy()},
	})

	// 按比例进行缩放
	for y := 0; y < dstRect.Dy(); y++ {
		for x := 0; x < dstRect.Dx(); x++ {
			srcX := x * src.Bounds().Dx() / dstRect.Dx()
			srcY := y * src.Bounds().Dy() / dstRect.Dy()
			stretched.Set(x, y, src.At(srcX, srcY))
		}
	}

	// 将拉伸图像绘制到目标图像上
	draw.Draw(dst, dstRect, stretched, image.Point{0, 0}, draw.Over)
}
